/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.engine.core.be;

import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.core.be.builtinimpls.BefBuiltInManager;
import com.inspur.edp.bef.core.be.builtinimpls.BefManagerCacheInfo;
import com.inspur.edp.bef.engine.api.IEngineBEManager;
import com.inspur.edp.bef.engine.common.GspBizEntityUtil;
import com.inspur.edp.bef.engine.core.BefEngineInfoCache;
import com.inspur.edp.bef.engine.core.dtm.BeforeQueryDtm;
import com.inspur.edp.bef.engine.core.dtm.BeforeRetrieveDtm;
import com.inspur.edp.bef.engine.entity.BeModelResInfo;
import com.inspur.edp.bef.engine.entity.serializer.EngineChangeDeserializer;
import com.inspur.edp.bef.engine.entity.serializer.EngineChangeSerializer;
import com.inspur.edp.bef.engine.entity.serializer.EngineRootDataDeserializer;
import com.inspur.edp.bef.engine.entity.serializer.EngineRootDataSerializer;
import com.inspur.edp.bef.spi.action.AbstractManagerAction;
import com.inspur.edp.bef.spi.entity.AbstractBizEntityDeSerializer;
import com.inspur.edp.bef.spi.entity.AbstractBizEntitySerializer;
import com.inspur.edp.bef.spi.entity.BefEntitySerConvertor;
import com.inspur.edp.cef.api.dataType.base.IAccessorCreator;
import com.inspur.edp.cef.entity.UQConstraintConfig;
import com.inspur.edp.cef.repository.utils.StringUtil;
import com.inspur.edp.cef.spi.determination.IEntityRTDtmAssembler;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefEntityResInfoImpl;
import com.inspur.edp.cef.spi.entity.resourceInfo.builinImpls.CefModelResInfoImpl;
import com.inspur.edp.cef.spi.jsonser.abstractcefchange.AbstractCefChangeJsonDeserializer;
import com.inspur.edp.cef.spi.jsonser.abstractcefchange.AbstractCefChangeSerializer;
import com.inspur.edp.cef.variable.api.manager.IVariableManager;
import com.inspur.edp.commonmodel.engine.api.common.CMEngineUtil;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.entity.object.GspUniqueConstraint;
import com.inspur.edp.das.commonmodel.util.CommonModelExtension;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.MetadataReference;
import io.iec.edp.caf.businessobject.api.entity.DevBasicBoInfo;
import io.iec.edp.caf.businessobject.api.service.DevBasicInfoService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import java.util.ArrayList;
import java.util.HashMap;
import org.springframework.util.StringUtils;

public class EngineBEManager extends BefBuiltInManager implements IEngineBEManager {

  private final GspBusinessEntity be;
  private GspMetadata metadata;

  public EngineBEManager(GspBusinessEntity be) {
    this.be = be;
  }

  public EngineBEManager(GspBusinessEntity be, GspMetadata metadata) {
    this.be = be;
    this.metadata = metadata;
  }

  @Override
  protected AbstractCefChangeSerializer getChangeSerializer() {
    return new EngineChangeSerializer(be,(CefEntityResInfoImpl) ((BeModelResInfo)getModelInfo()).getCustomResource(be.getMainObject().getCode()));
  }

  @Override
  protected AbstractCefChangeJsonDeserializer getChangeDeserializer() {
    return new EngineChangeDeserializer(be,(CefEntityResInfoImpl) ((BeModelResInfo)getModelInfo()).getCustomResource(be.getMainObject().getCode()));
  }

  @Override
  public AbstractBizEntitySerializer getDataSerialize() {
    return new BefEntitySerConvertor(this.getCefModelResourceInfo().getRootNodeCode(), true, this.getBEInfo().getBEType(),
            (CefEntityResInfoImpl)this.getCefModelResourceInfo().getCustomResource(this.getCefModelResourceInfo().getRootNodeCode()));
//    return new EngineRootDataSerializer(be,
//        (CefEntityResInfoImpl) ((BeModelResInfo)getModelInfo()).getCustomResource(be.getMainObject().getCode()));
  }

  @Override
  public AbstractBizEntityDeSerializer getDataDeserizlier() {
    return new EngineRootDataDeserializer(be,
        (CefEntityResInfoImpl) ((BeModelResInfo)getModelInfo()).getCustomResource(be.getMainObject().getCode()));
  }

  @Override
  protected IBusinessEntity createBusinessEntity(String dataId) {
    return new EngineBusinessEntity(be,(BeModelResInfo)innerGetModelInfo(),dataId,metadata);
  }

  @Override
  public IAccessorCreator getAccessorCreator() {
    return new AccessorCreator(be, getCefModelResourceInfo());
  }

  @Override protected IVariableManager createVariableManager(){
    if(be.getVariables() == null || be.getVariables().getContainElements().isEmpty()){
      return null;
    } else {
      return new com.inspur.edp.cef.variableengine.core.manager.EngineVariableManager(be.getVariables());
    }
  }

  @Override
  public Object executeCustomAction(String actionCode, Object... pars) {
    getBEManagerContext().checkAuthority(actionCode);
    AbstractManagerAction action = GspBizEntityUtil
        .instantiateMgrAction(be, actionCode, getBEManagerContext(), pars);
    return Execute(action);
  }

  @Override
  protected BefManagerCacheInfo getManagerCacheInfo() {
    if(metadata!=null && metadata.getProperties()!=null && metadata.getProperties().getCacheVersion()!=null && !"".equals(metadata.getProperties().getCacheVersion())) {
      return BefEngineInfoCache.getBefEngineInfo(be.getID(), metadata.getProperties().getCacheVersion()).getManagerCacheInfo();
    }else {
      return BefEngineInfoCache.getBefEngineInfo(be.getID()).getManagerCacheInfo();
    }
  }

  protected static BefManagerCacheInfo getManagerCacheInfo(GspBusinessEntity businessEntity) {
    GspMetadata metadata = CMEngineUtil.getMetadata(businessEntity.getID());
    if(metadata!=null && metadata.getProperties()!=null && metadata.getProperties().getCacheVersion()!=null && !"".equals(metadata.getProperties().getCacheVersion())) {
      return BefEngineInfoCache.getBefEngineInfo(businessEntity.getID(), metadata.getProperties().getCacheVersion()).getManagerCacheInfo();
    }else {
      return BefEngineInfoCache.getBefEngineInfo(businessEntity.getID()).getManagerCacheInfo();
    }
  }


  @Override
  public CefModelResInfoImpl getCefModelResourceInfo() {
    if (this.getManagerCacheInfo().getModelResInfo() != null)
      return (CefModelResInfoImpl) this.getManagerCacheInfo().getModelResInfo();

    BeModelResInfo resInfo= createResInfo(be);
    this.getManagerCacheInfo().setModelResInfo(resInfo);
    return resInfo;
  }

  public static CefModelResInfoImpl getCefModelResourceInfo(GspBusinessEntity businessEntity) {
    CefModelResInfoImpl cefModelResInfo = (CefModelResInfoImpl) getManagerCacheInfo(businessEntity).getModelResInfo();
    if(cefModelResInfo != null)
      return cefModelResInfo;

    BeModelResInfo resInfo= createResInfo(businessEntity);
    getManagerCacheInfo(businessEntity).setModelResInfo(resInfo);
    return resInfo;
  }

  public static BeModelResInfo createResInfo(GspBusinessEntity be) {
    GspMetadata metadata = CMEngineUtil.getMetadata(be.getId());
    String resMetaDataId = "";
    if(metadata.getRefs()!=null) {
      for (MetadataReference reference : metadata.getRefs()) {
        if (reference.getDependentMetadata().getType().equals("ResourceMetadata")) {
          resMetaDataId = reference.getDependentMetadata().getId();
          break;
        }
      }
    }

    String su = CommonModelExtension.getSUCode(be);
    if(StringUtils.isEmpty(su)) {
      DevBasicBoInfo devBasicBoInfo = SpringBeanUtils.getBean(DevBasicInfoService.class)
          .getDevBasicBoInfo(metadata.getHeader().getBizobjectID());
      if (devBasicBoInfo != null) {
        su = devBasicBoInfo.getSuCode();
        CommonModelExtension.setSUCode(be, su);
      }
    }
    BeModelResInfo resInfo= new BeModelResInfo(be,su,resMetaDataId);
    return resInfo;
  }

  @Override
  public HashMap<String, ArrayList<UQConstraintConfig>> getConstraintInfo(){
    java.util.HashMap<String,java.util.ArrayList<com.inspur.edp.cef.entity.UQConstraintConfig>> dict=new java.util.HashMap<>();
    for(GspBizEntityObject gspBizEntityObject:be.getAllNodes()){
      java.util.ArrayList<com.inspur.edp.cef.entity.UQConstraintConfig> list=new java.util.ArrayList<>();
      for(GspUniqueConstraint gspUniqueConstraint: gspBizEntityObject.getContainConstraints()){
        com.inspur.edp.cef.entity.UQConstraintConfig config=new com.inspur.edp.cef.entity.UQConstraintConfig();
        java.util.ArrayList<String> fields=new java.util.ArrayList<>();
        for(String element: gspUniqueConstraint.getElementList()){
          IGspCommonElement ele = gspBizEntityObject.findElement(element);
          fields.add(ele.getLabelID());
        }
        config.setConstraintFields(fields);
//        CustomizationRtService mdService = BefDtBeanUtil.getCustomizationRtService();
//        GspMetadata metadata = mdService.getMetadata(gspBizEntityObject.getBelongModelID());
//        DevBasicInfoService devBasicInfoService = SpringBeanUtils.getBean(DevBasicInfoService.class);
//        DevBasicBoInfo devBasicBoInfo = devBasicInfoService.getDevBasicBoInfo(metadata.getHeader().getBizobjectID());
//        String resMetaDataId = "";
//        for(MetadataReference reference:metadata.getRefs()){
//          if(reference.getDependentMetadata().getType() == "ResourceMetadata"){
//            resMetaDataId = reference.getDependentMetadata().getId();
//            break;
//          }
//        }
        String msg = getModelInfo().getCustomResource(gspBizEntityObject.getCode()).getUniqueConstraintMessage(gspUniqueConstraint.getCode());
        if(msg == null || msg.isEmpty()){
          msg = gspUniqueConstraint.getConstraintMessage();
        }
        config.setMessage(msg);
        list.add(config);
      }
      if(list.size()>0){
        dict.put(gspBizEntityObject.getCode(), list);
      }
    }

    return dict;
  }

  @Override
  protected IEntityRTDtmAssembler createBeforeQueryDtmAssembler() {
    return new BeforeQueryDtm(be.getMainObject());
  }

  @Override
  protected IEntityRTDtmAssembler createBeforeRetrieveDtmAssembler() {
    return new BeforeRetrieveDtm(be.getMainObject());
  }

}
